
/*!
	\file
	\brief Settings of the application.

		\author Igor Mironchik (igor.mironchik at gmail dot com).

		Copyright (c) 2010 - 2011 Igor Mironchik

	Permission is hereby granted, free of charge, to any person
	obtaining a copy of this software and associated documentation
	files (the "Software"), to deal in the Software without
	restriction, including without limitation the rights to use,
	copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the
	Software is furnished to do so, subject to the following
	conditions:

	The above copyright notice and this permission notice shall be
	included in all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
	OTHER DEALINGS IN THE SOFTWARE.
*/

// Qt include.
#include <QtXml/QDomDocument>

#include <QtCore/QFile>
#include <QtCore/QTextStream>

// eShopHelper include.
#include <eShopHelper/h/settings.hpp>


namespace eShopHelper {


//
// SettingsException
//

SettingsException::SettingsException( const QString & what )
	:	std::runtime_error( what.toLocal8Bit().data() )
	,	m_what( what )
{
}

SettingsException::~SettingsException() throw()
{
}

const QString &
SettingsException::whatAsQString() const throw()
{
	return m_what;
}


//
// Settings
//


Settings::Settings()
	:	m_cur( Goods::USD )
	,	m_vat( 0.0 )
	,	m_cur1( 0.0 )
	,	m_cur2( 0.0 )
	,	m_cur3( 0.0 )
	,	m_withVAT( true )
{
}

Settings::Settings( const Settings & s )
	:	m_cur( s.currency() )
	,	m_vat( s.vat() )
	,	m_cur1( s.cur1() )
	,	m_cur2( s.cur2() )
	,	m_cur3( s.cur3() )
	,	m_withVAT( s.isWithVAT() )
{
}

Settings::~Settings()
{
}

namespace /* anonymous */ {

const QString settingsDocName = QLatin1String( "settings" );
const QString currenciesTagName = QLatin1String( "currencies" );
const QString currencyTagName = QLatin1String( "currency" );
const QString USDValueName = QLatin1String( "USD" );
const QString EURValueName = QLatin1String( "EUR" );
const QString RUValueName = QLatin1String( "RU" );
const QString BYValueName = QLatin1String( "BY" );
const QString VATTagName = QLatin1String( "VAT" );
const QString CUR1TagName = QLatin1String( "CUR1" );
const QString CUR2TagName = QLatin1String( "CUR2" );
const QString CUR3TagName = QLatin1String( "CUR3" );
const QString withVATTagName = QLatin1String( "withVAT" );
const QString yesTagName = QLatin1String( "yes" );
const QString noTagName = QLatin1String( "no" );
const QString settingsFileName = QLatin1String( "./etc/settings.cfg" );

} /* namespace anonymous */

void
Settings::save()
{
	QDomDocument doc;

	QDomElement root = doc.createElement( settingsDocName );
	doc.appendChild( root );

	QDomElement currencies = doc.createElement( currenciesTagName );
	root.appendChild( currencies );

	QDomElement currency = doc.createElement( currencyTagName );

	switch( m_cur )
	{
		case Goods::USD :
			{
				QDomText value = doc.createTextNode( USDValueName );
				currency.appendChild( value );
			}
			break;
		case Goods::EURO :
			{
				QDomText value = doc.createTextNode( EURValueName );
				currency.appendChild( value );
			}
			break;
		case Goods::RU :
			{
				QDomText value = doc.createTextNode( RUValueName );
				currency.appendChild( value );
			}
			break;
		case Goods::BY :
			{
				QDomText value = doc.createTextNode( BYValueName );
				currency.appendChild( value );
			}
			break;
	}

	currencies.appendChild( currency );

	QDomElement vat = doc.createElement( VATTagName );
	QDomText vatValue = doc.createTextNode( QString::number( m_vat ) );
	vat.appendChild( vatValue );
	currencies.appendChild( vat );

	QDomElement cur1 = doc.createElement( CUR1TagName );
	QDomText cur1Value = doc.createTextNode( QString::number( m_cur1 ) );
	cur1.appendChild( cur1Value );
	currencies.appendChild( cur1 );

	QDomElement cur2 = doc.createElement( CUR2TagName );
	QDomText cur2Value = doc.createTextNode( QString::number( m_cur2 ) );
	cur2.appendChild( cur2Value );
	currencies.appendChild( cur2 );

	QDomElement cur3 = doc.createElement( CUR3TagName );
	QDomText cur3Value = doc.createTextNode( QString::number( m_cur3 ) );
	cur3.appendChild( cur3Value );
	currencies.appendChild( cur3 );

	QDomElement withVAT = doc.createElement( withVATTagName );
	QDomText withVATValue = doc.createTextNode( m_withVAT ? yesTagName : noTagName );
	withVAT.appendChild( withVATValue );
	currencies.appendChild( withVAT );

	QFile file( settingsFileName );
	file.open( QFile::WriteOnly | QFile::Truncate );

	if( file.isOpen() && file.isWritable() )
	{
		QTextStream stream( &file );

		doc.save( stream, 4 );

		file.close();
	}
	else
	{
		file.close();

		throw SettingsException( QLatin1String( "Unable to save file: \"" ) +
			settingsFileName + "\"" );
	}
}

void
Settings::load()
{
	QFile file( settingsFileName );

	if( file.open( QIODevice::ReadOnly ) )
	{
		QDomDocument doc;

		QString error;
		int errorLine = 0;

		if( !doc.setContent( &file, &error, &errorLine ) )
		{
			file.close();

			throw SettingsException( QLatin1String( "Unable to read file: \"" ) +
				settingsFileName + "\"" );
		}

		QDomElement elem = doc.documentElement();

		if( elem.tagName() != settingsDocName )
			throw SettingsException( QLatin1String( "There is no \"" ) +
				settingsDocName + "\" tag." );

		QDomNode currenciesNode = elem.namedItem( currenciesTagName );

		if( currenciesNode.isNull() )
			throw SettingsException( QLatin1String( "There is no \"" ) +
				currenciesTagName + "\" tag." );

		QDomElement currency = currenciesNode.namedItem( currencyTagName ).toElement();

		if( currency.isNull() )
			throw SettingsException( QLatin1String( "There is no \"" ) +
				currencyTagName + "\" tag." );
		else
		{
			const QString currencyValue = currency.text();

			if( currencyValue == USDValueName )
				m_cur = Goods::USD;
			else if( currencyValue == EURValueName )
				m_cur = Goods::EURO;
			else if( currencyValue == RUValueName )
				m_cur = Goods::RU;
			else if( currencyValue == BYValueName )
				m_cur = Goods::BY;
			else
				throw SettingsException( QLatin1String( "Unknown value for the currency type." ) );
		}

		QDomElement vat = currenciesNode.namedItem( VATTagName ).toElement();

		if( vat.isNull() )
			throw SettingsException( QLatin1String( "There is no \"" ) +
				VATTagName + "\" tag." );
		else
			m_vat = vat.text().toDouble();

		QDomElement cur1 = currenciesNode.namedItem( CUR1TagName ).toElement();

		if( cur1.isNull() )
			throw SettingsException( QLatin1String( "There is no \"" ) +
				CUR1TagName + "\" tag." );
		else
			m_cur1 = cur1.text().toDouble();

		QDomElement cur2 = currenciesNode.namedItem( CUR2TagName ).toElement();

		if( cur2.isNull() )
			throw SettingsException( QLatin1String( "There is no \"" ) +
				CUR2TagName + "\" tag." );
		else
			m_cur2 = cur2.text().toDouble();

		QDomElement cur3 = currenciesNode.namedItem( CUR3TagName ).toElement();

		if( cur3.isNull() )
			throw SettingsException( QLatin1String( "There is no \"" ) +
				CUR3TagName + "\" tag." );
		else
			m_cur3 = cur3.text().toDouble();

		QDomElement withVAT = currenciesNode.namedItem( withVATTagName ).toElement();

		if( withVAT.isNull() )
			throw SettingsException( QLatin1String( "There is no \"" ) +
				withVATTagName + "\" tag." );
		else
			m_withVAT = ( withVAT.text() == yesTagName ? true : false );

		file.close();
	}
	else
		throw SettingsException( QLatin1String( "Unable to read file: \"" ) +
			settingsFileName + "\"" );
}

Goods::Currency
Settings::currency() const
{
	return m_cur;
}

double
Settings::vat() const
{
	return m_vat;
}

double
Settings::cur1() const
{
	return m_cur1;
}

double
Settings::cur2() const
{
	return m_cur2;
}

double
Settings::cur3() const
{
	return m_cur3;
}

bool
Settings::isWithVAT() const
{
	return m_withVAT;
}

void
Settings::setCurrency( Goods::Currency cur )
{
	m_cur = cur;
}

void
Settings::setVAT( double vat )
{
	m_vat = vat;
}

void
Settings::setCur1( double cur1 )
{
	m_cur1 = cur1;
}

void
Settings::setCur2( double cur2 )
{
	m_cur2 = cur2;
}

void
Settings::setCur3( double cur3 )
{
	m_cur3 = cur3;
}

void
Settings::setWithVAT( bool yes )
{
	m_withVAT = yes;
}

void
Settings::operator = ( const Settings & s )
{
	m_cur = s.currency();
	m_vat = s.vat();
	m_cur1 = s.cur1();
	m_cur2 = s.cur2();
	m_cur3 = s.cur3();
	m_withVAT = s.isWithVAT();
}

} /* namespace eShopHelper */
